﻿// <copyright file="GlobalVariables.cs" company="Ecole Normale Supérieure">
// Released under GPLv2
// </copyright>
// <summary>Contains the GlobalVariable provider</summary>

namespace Sqwarea.Persistence.Azure
{
    using System;
    using System.Runtime.Serialization;
    using Lokad.Cloud.Storage;

    /// <summary>
    /// Provider for Gloabls Variables
    /// </summary>
    public class GlobalVariables : IGlobalVariables
    {
        /// <summary>
        /// blob provider
        /// </summary>
        private readonly IBlobStorageProvider _blobProvider;

        /// <summary>
        /// Name of the blob containing the KingId
        /// </summary>
        private const string KingIdBlobName = "king-id";

        /// <summary>
        /// Name of the blob containing the Radius at witch new Kings are placed
        /// </summary>
        private const string RadiusBlobName = "radius";

        /// <summary>
        /// Initializes a new instance of the GlobalVariables class.
        /// </summary>
        /// <param name="blobProvider"> a blob provider</param>
        [CLSCompliantAttribute(false)]
        public GlobalVariables(IBlobStorageProvider blobProvider)
        {
            if (null == blobProvider)
            {
                throw new ArgumentNullException("blobProvider", "blobProvider must not be null");
            }

            _blobProvider = blobProvider;
            ////this._blobProvider.CreateContainer(BlobName.GetContainerName<GlobalVariableName>());
        }

        /// <summary>
        /// Gets or sets next king Id
        /// WARNING : Only used by Batch to put new Id in the Id queue
        /// </summary>
        public long NextKingId
        {
            get
            {
                var blob = _blobProvider.GetBlob(new GlobalVariableName(KingIdBlobName));
                if (blob.HasValue)
                {
                    return blob.Value.Long;
                }

                return 1;
            }

            set
            {
                var blob = new GlobalVariable { Long = value };
                var blobName = new GlobalVariableName(KingIdBlobName);
                _blobProvider.PutBlob(blobName, blob);
            }
        }

        /// <summary>
        /// Gets or sets current radius used to create new kings.
        /// New kingdom are placed at newKingsRadius distance from (0,0).
        /// </summary>
        public uint NewKingsRadius
        {
            get
            {
                var blob = _blobProvider.GetBlob(new GlobalVariableName(RadiusBlobName));
                if (blob.HasValue)
                {
                    return blob.Value.Uint;
                }
                
                return 0;
            }

            set
            {
                var blob = new GlobalVariable { Uint = value };
                var blobName = new GlobalVariableName(RadiusBlobName);
                _blobProvider.PutBlob(blobName, blob);
            }
        }

        /// <summary>
        /// Private class used to store global variables
        /// </summary>
        [DataContract]
        private class GlobalVariable
        {
            /// <summary>
            /// Gets or sets a stored long...
            /// </summary>
            [DataMember]
            public long Long { get; set; }

            /// <summary>
            /// Gets or sets a stored uint...
            /// </summary>
            [DataMember]
            public uint Uint { get; set; }
        }

        /// <summary>
        /// Class enabling to select a Global Variable on the blob storage (kind of strong typed key)
        /// </summary>
        private class GlobalVariableName : BlobName<GlobalVariable>
        {
            /// <summary>
            /// Gets the Name of the variable, which will be the name of the blob
            /// </summary>
            [Rank(0)]
            public readonly string Name;

            /// <summary>
            /// Initializes a new instance of the GlobalVariableName class.
            /// </summary>
            /// <param name="name">name of the stored global variable</param>
            public GlobalVariableName(string name)
            {
                if (String.IsNullOrEmpty(name))
                {
                    throw new ArgumentOutOfRangeException("name", "name must not be null or empty");
                }

                Name = name;
            }

            /// <summary>
            /// Name of blob container
            /// </summary>
            public override string ContainerName
            {
                get { return "sqwarea-global-variables-container"; }
            }
        }
    }
}
